package org.infodavid.common.impl.persistence;

import java.util.Collection;

import org.infodavid.common.IBuilder;
import org.infodavid.common.model.IImageData;
import org.infodavid.common.model.ModelFactory;
import org.infodavid.common.model.components.IEMail;
import org.infodavid.common.model.components.IGeoLocation;
import org.infodavid.common.model.components.ILocation;
import org.infodavid.common.model.components.IOwnerDetails;
import org.infodavid.common.model.components.IPhone;
import org.infodavid.common.model.components.IUri;

/**
 * The Class CopyUtil.
 */
public final class CopyUtil {

  /**
   * The Constructor.
   */
  private CopyUtil() {
    super();
  }

  /**
   * Copy.
   * @param from the from
   * @return the geo location
   * @throws InstantiationException the instantiation exception
   */
  public static IGeoLocation copy(final IGeoLocation from) throws InstantiationException {
    final IGeoLocation data;

    if (from == null) {
      data = null;
    }
    else {
      data = ModelFactory.getInstance().create(IGeoLocation.class);

      data.setLatitude(from.getLatitude());
      data.setLongitude(from.getLongitude());
    }

    return data;
  }

  /**
   * Copy.
   * @param from the from
   * @return the email
   * @throws InstantiationException the instantiation exception
   */
  public static IEMail copy(final IEMail from) throws InstantiationException {
    final IEMail data;

    if (from == null) {
      data = null;
    }
    else {
      data = copy(from, ModelFactory.getInstance().getBuilder(IEMail.class));
    }

    return data;
  }

  /**
   * Copy.
   * @param from the from
   * @param builder the builder
   * @return the email
   * @throws InstantiationException the instantiation exception
   */
  public static IEMail copy(final IEMail from, final IBuilder<IEMail> builder)
      throws InstantiationException {
    final IEMail data;

    if (from == null) {
      data = null;
    }
    else {
      data = builder.create();

      data.setType(from.getType());
      data.setValue(from.getValue());
    }

    return data;
  }

  /**
   * Copy.
   * @param from the from
   * @param builder the builder
   * @return the phone
   * @throws InstantiationException the instantiation exception
   */
  public static IPhone copy(final IPhone from, final IBuilder<IPhone> builder)
      throws InstantiationException {
    final IPhone data;

    if (from == null) {
      data = null;
    }
    else {
      data = builder.create();

      data.setType(from.getType());
      data.setValue(from.getValue());
    }

    return data;
  }

  /**
   * Copy.
   * @param from the from
   * @param builder the builder
   * @return the uri
   * @throws InstantiationException the instantiation exception
   */
  public static IUri copy(final IUri from, final IBuilder<IUri> builder)
      throws InstantiationException {
    final IUri data;

    if (from == null) {
      data = null;
    }
    else {
      data = builder.create();

      data.setType(from.getType());
      data.setValue(from.getValue());
    }

    return data;
  }

  /**
   * Copy phones.
   * @param from the from
   * @param results the results
   * @param deep the deep
   * @throws InstantiationException the instantiation exception
   */
  public static void copyPhones(final Collection<IPhone> from, final Collection<IPhone> results,
      final boolean deep) throws InstantiationException {
    if (!(from == null || from.isEmpty())) {
      if (deep) {
        final IBuilder<IPhone> builder = ModelFactory.getInstance().getBuilder(IPhone.class);

        for (final IPhone item : from) {
          results.add(copy(item, builder));
        }
      }
      else {
        results.addAll(from);
      }
    }
  }

  /**
   * Copy uris.
   * @param from the from
   * @param results the results
   * @param deep the deep
   * @throws InstantiationException the instantiation exception
   */
  public static void copyUris(final Collection<IUri> from, final Collection<IUri> results,
      final boolean deep) throws InstantiationException {
    if (!(from == null || from.isEmpty())) {
      if (deep) {
        final IBuilder<IUri> builder = ModelFactory.getInstance().getBuilder(IUri.class);

        for (final IUri item : from) {
          results.add(copy(item, builder));
        }
      }
      else {
        results.addAll(from);
      }
    }
  }

  /**
   * Copy emails.
   * @param from the from
   * @param results the results
   * @param deep the deep
   * @throws InstantiationException the instantiation exception
   */
  public static void copyEmails(final Collection<IEMail> from, final Collection<IEMail> results,
      final boolean deep) throws InstantiationException {
    if (!(from == null || from.isEmpty())) {
      if (deep) {
        final IBuilder<IEMail> builder = ModelFactory.getInstance().getBuilder(IEMail.class);

        for (final IEMail item : from) {
          results.add(copy(item, builder));
        }
      }
      else {
        results.addAll(from);
      }
    }
  }

  /**
   * Copy image.
   * @param from the from
   * @param deep the deep
   * @return the image data
   * @throws InstantiationException the instantiation exception
   */
  public static IImageData copyImage(final IImageData from, final boolean deep)
      throws InstantiationException {
    IImageData to = null;

    if (!(from == null || from.getValue() == null)) {
      to = ModelFactory.getInstance().create(IImageData.class);

      if (deep) {

        to.setType(from.getType());
        to.setValue(from.getValue().clone());
      }
      else {
        to.setType(from.getType());
        to.setValue(from.getValue());
      }
    }

    return to;
  }

  /**
   * Copy.
   * @param from the from
   * @param deep the deep
   * @param asNew the as new
   * @return the location
   * @throws InstantiationException the instantiation exception
   */
  public static ILocation copy(final ILocation from, final boolean deep, final boolean asNew)
      throws InstantiationException {
    final ILocation to;

    if (from == null) {
      to = null;
    }
    else {
      to = ModelFactory.getInstance().create(ILocation.class);

      to.setAddress(from.getAddress());
      to.setCountry(from.getCountry());
      to.setGeoLocation(CopyUtil.copy(from.getGeoLocation()));
      to.setCity(from.getCity());
      to.setZipCode(from.getZipCode());
      to.setName(from.getName());
      to.setType(from.getType());
    }

    return to;
  }

  /**
   * Copy.
   * @param from the from
   * @param to the to
   * @param deep the deep
   * @param asNew the as new
   * @throws InstantiationException the instantiation exception
   */
  public static void copyLocations(final Collection<ILocation> from,
      final Collection<ILocation> to, final boolean deep, final boolean asNew)
      throws InstantiationException {
    to.clear();

    if (from == null) {}
    else if (deep) {
      for (final ILocation item : from) {
        to.add(copy(item, deep, asNew));
      }
    }
    else {
      to.addAll(from);
    }
  }

  /**
   * Copy.
   * @param from the from
   * @param to the to
   * @throws InstantiationException the instantiation exception
   */
  public static void copy(final IOwnerDetails from, final IOwnerDetails to)
      throws InstantiationException {
    if (!(from == null || to == null)) {
      to.setGroup(from.getGroup());
      to.setUser(from.getUser());
      to.setVisibility(from.getVisibility());
    }
  }
}
